package com.flyxiaozhu.erp.core.services;

import com.flyxiaozhu.erp.core.entities.GoodsCategory;
import com.flyxiaozhu.erp.core.helper.DateHelper;
import com.flyxiaozhu.erp.core.libs.Constants;
import com.flyxiaozhu.erp.core.repositories.GoodsCategoryRepository;
import com.flyxiaozhu.erp.core.utils.ObjectMapUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.*;
import java.util.*;

@Service
public class GoodsCategoryService {
    @Autowired
    GoodsCategoryRepository goodsCategoryRepository;

    public List<GoodsCategory> getTree() {
        List<GoodsCategory> all = goodsCategoryRepository.findByStatus(Constants.COMMON_STATUS_NORMAL);

        return getChildren(null, all);
    }

    // 后台专用
    public List<GoodsCategory> getTree2() {
        List<GoodsCategory> all = goodsCategoryRepository.findAll();

        return getChildren(null, all);
    }

    // 只获取前两级分类
    public List<GoodsCategory> getTree3(long num) {
        List<GoodsCategory> all = goodsCategoryRepository.findAll(new Specification<GoodsCategory>() {
            @Override
            public Predicate toPredicate(Root<GoodsCategory> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Path level = root.get("level");
                Predicate predicate = criteriaBuilder.le(level, num);
                criteriaQuery.where(predicate);
                return null;
            }
        });

        return getChildren(null, all);
    }


    public Set<Long> getChildrenIds(List<GoodsCategory> tree, long pid) {
        GoodsCategory node = findNode(tree, pid);
        if (node == null) {
            return null;
        }

        return collectChildrenId(node, new HashSet<>());
    }

    private GoodsCategory findNode(List<GoodsCategory> tree, Long id) {
        for (GoodsCategory node : tree) {
            if (node.getId() == id) {
                return node;
            }

            GoodsCategory t = findNode(node.getChildren(), id);
            if (t != null) {
                return t;
            }
        }

        return null;
    }

    private Set<Long> collectChildrenId(GoodsCategory node, Set<Long> set) {
        for (GoodsCategory child : node.getChildren()) {
            set.add(child.getId());

            set = collectChildrenId(child, set);
        }

        return set;
    }

    /**
     * 取得多维数组结构
     *
     * @param parent
     * @param all
     * @return
     */
    private List<GoodsCategory> getChildren(GoodsCategory parent, List<GoodsCategory> all) {
        List<GoodsCategory> nodes = new ArrayList<>();
        long pid = parent == null ? 0 : parent.getId();

        for (GoodsCategory item : all) {
            if (item.getPid() == pid) {
                nodes.add(item);
                item.setParent(parent);
                item.setChildren(getChildren(item, all));
            }
        }

        return nodes;
    }

    /**
     * 格式化分类结构
     *
     * @param tree
     * @return
     */
    public List<Map> getFormattedTypes(List<GoodsCategory> tree) {
        List<Map> data = new ArrayList<>();
        return tree2row(tree, data, false);
    }

    /**
     * 取得后台展示结构的分类
     *
     * @param tree
     * @param data
     * @param disabled
     * @return
     */
    private List<Map> tree2row(List<GoodsCategory> tree, List<Map> data, boolean disabled) {
        for (int index = 0; index < tree.size(); index++) {
            GoodsCategory node = tree.get(index);
            String p = "";
            String m = index == tree.size() - 1 ? "└─ " : "├─ ";
            int level = node.getLevel();
            if (level > 1) {
                p = StringUtils.repeat("　　", level - 2) + m;
            }

            Map<String, Object> o = ObjectMapUtils.beanToMap(node);
            o.put("name", p + node.getName());
            o.put("disabled", disabled || node.getStatus() != 0);
            data.add(o);

            if (tree.get(index).getChildren().size() > 0) {
                this.tree2row(tree.get(index).getChildren(), data, (Boolean) o.get("disabled"));
            }
        }

        return data;
    }

    /**
     * 判断分类是否父类变成了子类的子类
     *
     * @param node
     * @param nodeId
     * @return
     */
    private boolean hasRing(GoodsCategory node, Long nodeId) {
        GoodsCategory parent = this.findById(node.getPid());
        if (parent == null) {
            return false;
        }
        if (nodeId.equals(parent.getId())) {
            return true;
        }

        return hasRing(parent, nodeId);
    }

    public Boolean hasRing(GoodsCategory goodsCategory) {

        return hasRing(goodsCategory, goodsCategory.getId());
    }

    public GoodsCategory save(GoodsCategory goodsCategory) {
        if (goodsCategory.getPid() == 0) {
            goodsCategory.setLevel(1);
            return goodsCategoryRepository.save(goodsCategory);
        }
        // 得到level
        int level = this.getLevel(goodsCategory.getPid(), 1);
        goodsCategory.setLevel(level);

        return goodsCategoryRepository.save(goodsCategory);
    }

    public GoodsCategory update(GoodsCategory goodsCategory, GoodsCategory oldCategory) {
        int oldLevel = oldCategory.getLevel();
        // 得到level
        int level = this.getLevel(goodsCategory.getPid(), 1);
        goodsCategory.setLevel(level);

        // 改变子类等级
        List<GoodsCategory> categories = goodsCategoryRepository.findByPid(goodsCategory.getId());
        for (GoodsCategory item : categories) {
            item.setLevel(level + item.getLevel() - oldLevel);
            goodsCategoryRepository.save(item);
        }

        goodsCategory.setUpdateTime(DateHelper.getStringDate());
        return goodsCategoryRepository.save(goodsCategory);
    }

    /**
     * 根据pid查找所属于level
     *
     * @param pid 父Id
     * @param i   level
     * @return int
     */
    private int getLevel(long pid, int i) {
        if (pid == 0) {
            return i;
        }
        GoodsCategory goodsCategory = goodsCategoryRepository.findById(pid).orElse(null);
        return this.getLevel(goodsCategory.getPid(), ++i);
    }

    public GoodsCategory findById(Long id) {
        return goodsCategoryRepository.findById(id).orElse(null);
    }

    /**
     * 删除分类及其子类
     *
     * @param goodsCategoryList
     */
    public void delete(List<GoodsCategory> goodsCategoryList) {
        List<GoodsCategory> children = getChildren(null, goodsCategoryList);
        deleteRecursion(children);
    }

    /**
     * 递归删除
     *
     * @param goodsCategoryList
     */
    private void deleteRecursion(List<GoodsCategory> goodsCategoryList) {
        for (GoodsCategory goodsCategory : goodsCategoryList) {
            if (goodsCategory.getChildren() != null) {
                deleteRecursion(goodsCategory.getChildren());
            }
            goodsCategoryRepository.delete(goodsCategory);
        }

    }
}
